"""This module provides the commonly geoimage related functions,
   implemented using rasterio or subprocess call to gdal binaries

- convert_dtype_np2rio
- read_metadata_from_geoimage
- TODO below
    - read_data_from_geoimage
    - read_data_from_geoimage_by_block
    - write_data_to_geoimage
    - warp_geoimage
    - mosaic_geoimage
    - rasterize_geom
    - polygonize_geoimage
"""
from typing import Union

import numpy as np

import rasterio


def convert_dtype_np2rio(np_dtype):
    """convert numpy dtype to rasterio dtype"""
    if np_dtype == np.uint8:
        return rasterio.uint8
    elif np_dtype == np.uint16:
        return rasterio.uint16
    elif np_dtype == np.int16:
        return rasterio.int16
    elif np_dtype == np.float32:
        return rasterio.float32
    else:
        raise ValueError(
            (
                "Currently we have not supported numpy dtype {}, "
                "only np.uint8 and np.uint16 supported"
            ).format(np_dtype)
        )


def read_metadata_from_geoimage(geoimage: Union[str, rasterio.DatasetReader]):
    """Read basic metadata information from a given geoimage

    Parameters
    ----------
    geoimage : str or rasterio.DatasetReader
        File path to a geoimage supported by rasterio, or an opened `rasterio.DatasetReader`.

    Returns
    -------
    meta : dict
        Basic metadata information as a dictionary from the given geoimage,
        the following keys should be present:
            - dtype: data type
            - nodata: nodata value
            - width: width of the image
            - height: height of the image
            - count: number of bands of the image
            - crs: coordinate reference system of the image
            - transform: geotransform as an affine matrix
    """
    keys_to_collect = (
        "dtype",
        "nodata",
        "width",
        "height",
        "count",
        "crs",
        "transform",
    )
    meta = {}
    if isinstance(geoimage, rasterio.DatasetReader):
        profile = geoimage.profile
    else:
        with rasterio.open(geoimage) as rst_tmp:
            profile = rst_tmp.profile
    for key in keys_to_collect:
        meta[key] = profile[key]
    return meta


def read_data_from_geoimage(fpath_geoimage, aoi=None):
    raise NotImplementedError


def read_data_from_geoimage_by_block(
    fpath_geoimage,
    aoi=None,
    block_x_size=1024,
    block_y_size=1024,
    buffer_x_size=0,
    buffer_y_size=0,
):
    raise NotImplementedError


def write_data_to_geoimage(nda_data, fpath_geoimage):
    raise NotImplementedError


def warp_geoimage(fpath_geoimage_src, fpath_geoimage_dest, dest_srs):
    raise NotImplementedError


def mosaic_geoimages(lst_geoimages, dest_srs=None):
    raise NotImplementedError


def rasterize_geom(geom, fpath_geoimage=None):
    pass


def polygonize_geoimage(fpath_geoimage):
    pass
